package restless.core.managers {
	
	import flash.events.KeyboardEvent;
	
	import restless.core.gameObjs.RLEManagedObj;
	import restless.core.interfaces.IKeyControled;
	
	/**
	 * 
	 * @author Adam 'Atomic' Saltsman, Flixel 
	 *		   Jordan 'No Bueno' Laine, Restless Engine
	 * 
	 */
	
	public class RLEKeyboardManager extends RLEManagedObj {
		private var _actions:Array;
		
		private var keyPress:int;
		private var bCustomKeys:Boolean = false;
		private var tempKeyControl:IKeyControled;
		
		private var vActiveKeyCodes:Vector.<int>;
		private var vActiveKeyStrings:Vector.<String>;
		private var vDefaultKeys:Vector.<String>;
		private var vCustomKeys:Vector.<String>;
		private var vKeyboardObjs:Vector.<IKeyControled>;
		private var vKeyboardObjsCache:Vector.<IKeyControled>;
		
		private var tempKeys:Vector.<String>;
		
		internal var _lookup:Array = [];
		
		public function RLEKeyboardManager() {
			setRE();
			
			_lookup = [];
			vActiveKeyCodes = new Vector.<int>;
			vActiveKeyStrings = new Vector.<String>;
			vDefaultKeys = new Vector.<String>;
			vCustomKeys = new Vector.<String>;
			vKeyboardObjs = new Vector.<IKeyControled>;
			vKeyboardObjsCache = new Vector.<IKeyControled>;
			
			addKeys();
			addListeners();
		}
		
		private function addListeners():void {
			stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDown);
			stage.addEventListener(KeyboardEvent.KEY_UP, keyUp); 
		}
		
		private function removeListeners():void {
			stage.removeEventListener(KeyboardEvent.KEY_DOWN, keyDown);
			stage.removeEventListener(KeyboardEvent.KEY_UP, keyUp); 
		}
		
		private function keyDown(e:KeyboardEvent):void {
			i = vActiveKeyCodes.length -1;
			for (i; i > -1; i--) {
				if (e.keyCode == vActiveKeyCodes[i]) {
					var j:int = vKeyboardObjs.length - 1;
					for (j; j > -1; j--) {
						vKeyboardObjs[j].input( vActiveKeyStrings[i] );
					}
				}
			}
		}
		
		private function keyUp(e:KeyboardEvent):void {
			
		}
		
		public function addToKeyboardListen(asset:IKeyControled):void {
			tempKeyControl = asset;
			i = vKeyboardObjs.indexOf(tempKeyControl);
			if (i < 0) {
				vKeyboardObjs.push(asset);
				//tempKeyControl.setInputActions(_actions);
			}
			tempKeyControl = null;
		} 
		
		public function removeFromKeyboardListen(asset:IKeyControled):void {
			i = vKeyboardObjs.indexOf(asset);
			if (i > -1) {
				vKeyboardObjs.splice(i, 1);
			}
		}
		
		public function getActiveKeyCodes():Vector.<int> {
			return vActiveKeyCodes;
		}
		
		public function defaultKeys():void {
			
		}
		
		public function deactivateAllKeys():void {
			vActiveKeyStrings = null;
			vActiveKeyCodes = null;
		}
		
		public function activateAllKeys():void {
			var num:int = _lookup.length;
			for (num; num > -1; num-=2) {
				activateKey(_lookup[num]);
			}
		}
		
		public function activateKeys(keys:Vector.<String>):void {
			tempKeys = keys;
			
			if (defaultKeys == null) {
				vDefaultKeys = tempKeys;
			} else {
				vCustomKeys = tempKeys;
			}
			
			var num:int;
			for (i = 0; i < tempKeys.length - 1; i++) {
				tempString = tempKeys[i];
				num = vActiveKeyStrings.indexOf(tempString);
				if (num < 0) {
					vActiveKeyStrings.push(tempString);
					vActiveKeyCodes.push( getKey(tempString)[1] );
				}
			}
		}
		
		public function activateKey(key:String):void {
			tempString = key;
			i = vActiveKeyStrings.indexOf(tempString);
			if (i < 0) {
				vActiveKeyStrings.push(tempString);
				var num:int = _lookup.indexOf(tempString);
				vActiveKeyCodes.push( _lookup[num+1]);
			}
		}
		
		public function deactivateKey(key:String):void {
			tempString = key;
			i = vActiveKeyStrings.indexOf(tempString);
			if (i > -1) {
				vActiveKeyStrings.splice(i, 1);
				vActiveKeyCodes.splice(i, 1 );
			}
		}
		
		private function getKeyCode(key:String):int {
			tempString = key;
			i = _lookup.indexOf(tempString) + 1;
			return _lookup[i];
		}
		
		public function setActions(actions:Array):void {
			_actions = actions;
		}
		
		private function addKey(KeyName:String, KeyCode:uint):void	{
			_lookup.push(KeyName, KeyCode);
		}
		
		public function getKey(name:String = null, num:int = -1):Array {
			tempString = name;
			var keyNum:int = num;
			var index:int;
			var aKey:Array
			
			if (tempString != null) {
				index = _lookup.indexOf(tempString);
				if (index > -1) {
					keyNum = _lookup[index+1];
				} else { 
					return aKey = [];
				}
				
			} else if (keyNum > -1) {
				index = _lookup.indexOf(tempString);
				if (index >= 0) {
					tempString = _lookup[index-1];
				} else {
					return aKey = [];
				}
			}
			
			aKey = [tempString, keyNum];
			return aKey;
		}
		
		private function addKeys():void {
			
			//LETTERS
			i = 65;
			while(i <= 90)
				addKey(String.fromCharCode(i),i++);
			
			//NUMBERS
			i = 48;
			addKey("ZERO",i++);
			addKey("ONE",i++);
			addKey("TWO",i++);
			addKey("THREE",i++);
			addKey("FOUR",i++);
			addKey("FIVE",i++);
			addKey("SIX",i++);
			addKey("SEVEN",i++);
			addKey("EIGHT",i++);
			addKey("NINE",i++);
			i = 96;
			addKey("NUMPADZERO",i++);
			addKey("NUMPADONE",i++);
			addKey("NUMPADTWO",i++);
			addKey("NUMPADTHREE",i++);
			addKey("NUMPADFOUR",i++);
			addKey("NUMPADFIVE",i++);
			addKey("NUMPADSIX",i++);
			addKey("NUMPADSEVEN",i++);
			addKey("NUMPADEIGHT",i++);
			addKey("NUMPADNINE",i++);
			addKey("PAGEUP", 33);
			addKey("PAGEDOWN", 34);
			addKey("HOME", 36);
			addKey("END", 35);
			addKey("INSERT", 45);
			
			//FUNCTION KEYS
			i = 1;
			while(i <= 12)
				addKey("F"+i,111+(i++));
			
			//SPECIAL KEYS + PUNCTUATION
			addKey("ESCAPE",27);
			addKey("MINUS",189);
			addKey("NUMPADMINUS",109);
			addKey("PLUS",187);
			addKey("NUMPADPLUS",107);
			addKey("DELETE",46);
			addKey("BACKSPACE",8);
			addKey("LBRACKET",219);
			addKey("RBRACKET",221);
			addKey("BACKSLASH",220);
			addKey("CAPSLOCK",20);
			addKey("SEMICOLON",186);
			addKey("QUOTE",222);
			addKey("ENTER",13);
			addKey("SHIFT",16);
			addKey("COMMA",188);
			addKey("PERIOD",190);
			addKey("NUMPADPERIOD",110);
			addKey("SLASH",191);
			addKey("NUMPADSLASH",191);
			addKey("CONTROL",17);
			addKey("ALT",18);
			addKey("SPACE",32);
			addKey("UP",38);
			addKey("DOWN",40);
			addKey("LEFT",37);
			addKey("RIGHT",39);
			addKey("TAB",9);
		}
		
		override public function set pause(bool:Boolean):void {
			super.pause = bool;
			if (pause) {
				i = vKeyboardObjs.length -1;
				for (i; i > -1; i--) {
					vKeyboardObjsCache.push(vKeyboardObjs[i]);
				}
				vKeyboardObjs.length = 0;
			} else {
				vKeyboardObjs.length = 0;
				i = vKeyboardObjsCache.length -1;
				for (i; i > -1; i--) {
					vKeyboardObjs.push(vKeyboardObjsCache[i]);
				}
				vKeyboardObjsCache.length = 0;
			}
		}
		
		
		public override function dispose():void {
			removeListeners();
			
			tempKeyControl = null;
			vActiveKeyCodes = null;
			vActiveKeyStrings = null;
			vDefaultKeys = null;
			vCustomKeys = null;
			vKeyboardObjs = null;
			vKeyboardObjsCache = null;
			_lookup = null;
			
		}
	}
}